1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.thirdparty.publicsuffix;
18
19 import com.google.common.annotations.GwtCompatible;
20 import com.google.common.base.Joiner;
21 import com.google.common.collect.ImmutableMap;
22 import com.google.common.collect.Lists;
23
24 import java.util.List;
25
26
27
28
29 @GwtCompatible
30 class TrieParser {
31
32 private static final Joiner PREFIX_JOINER = Joiner.on("");
33
34
35
36
37
38 static ImmutableMap<String, PublicSuffixType> parseTrie(CharSequence encoded) {
39 ImmutableMap.Builder<String, PublicSuffixType> builder = ImmutableMap.builder();
40 int encodedLen = encoded.length();
41 int idx = 0;
42 while (idx < encodedLen) {
43 idx += doParseTrieToBuilder(
44 Lists.<CharSequence>newLinkedList(),
45 encoded.subSequence(idx, encodedLen),
46 builder);
47 }
48 return builder.build();
49 }
50
51
52
53
54
55
56
57
58
59
60 private static int doParseTrieToBuilder(
61 List<CharSequence> stack,
62 CharSequence encoded,
63 ImmutableMap.Builder<String, PublicSuffixType> builder) {
64
65 int encodedLen = encoded.length();
66 int idx = 0;
67 char c = '\0';
68
69
70 for ( ; idx < encodedLen; idx++) {
71 c = encoded.charAt(idx);
72 if (c == '&' || c == '?' || c == '!' || c == ':' || c == ',') {
73 break;
74 }
75 }
76
77 stack.add(0, reverse(encoded.subSequence(0, idx)));
78
79 if (c == '!' || c == '?' || c == ':' || c == ',') {
80
81
82
83
84 String domain = PREFIX_JOINER.join(stack);
85 if (domain.length() > 0) {
86 builder.put(domain, PublicSuffixType.fromCode(c));
87 }
88 }
89 idx++;
90
91 if (c != '?' && c != ',') {
92 while (idx < encodedLen) {
93
94 idx += doParseTrieToBuilder(stack, encoded.subSequence(idx, encodedLen), builder);
95 if (encoded.charAt(idx) == '?' || encoded.charAt(idx) == ',') {
96
97 idx++;
98 break;
99 }
100 }
101 }
102 stack.remove(0);
103 return idx;
104 }
105
106
107
108
109
110
111 private static CharSequence reverse(CharSequence s) {
112 int length = s.length();
113 if (length <= 1) {
114 return s;
115 }
116
117 char[] buffer = new char[length];
118 buffer[0] = s.charAt(length - 1);
119
120 for (int i = 1; i < length; i++) {
121 buffer[i] = s.charAt(length - 1 - i);
122 if (Character.isSurrogatePair(buffer[i], buffer[i - 1])) {
123 swap(buffer, i - 1, i);
124 }
125 }
126
127 return new String(buffer);
128 }
129
130 private static void swap(char[] buffer, int f, int s) {
131 char tmp = buffer[f];
132 buffer[f] = buffer[s];
133 buffer[s] = tmp;
134 }
135 }